﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace Normalify
{
    public static class DataTableExtension
    {
        public static IDataTable ReadCsv(string fileName, Func<string, Type> getType,  char delim = '\t')
        {
            var table = default(IDataTable);
            var cols = new List<IDataColumn>();

	        var lines = 0L;
            using (var file = File.OpenText(fileName))
            {
                while (!file.EndOfStream)
                {
                    var line = file.ReadLine();
	                lines ++;
                    if (line != null && !string.IsNullOrWhiteSpace(line) && table == null)
                    {
                        var strs = line.Split(delim);
                        table = CreateDqDataTable(strs, strs.Select(getType));
                        cols.AddRange(table.Columns);
                    }
                    else if (line != null && !string.IsNullOrWhiteSpace(line) && table != null)
                    {
                        var strs = line.Split(delim);
                        var data = new object[cols.Count];

						if (cols.Count != strs.Length)
						{
							Console.WriteLine("Line {0} is expected to have {1} cols but it has {2} cols.!", lines, cols.Count, strs.Length);
							continue;
						}
                        for (var i = 0; i < cols.Count; i++)
                        {
                            data[i] = string.IsNullOrWhiteSpace(strs[i]) ? DefaultValue(table.GetDataType(cols[i])) :
								Convert.ChangeType(strs[i], UnderLyingType(table.GetDataType(cols[i])));
                        }
                        ((IDataRowAdder) table).AddRow(data);
                    }
                }
            }
            return table;
        }

	    private static Type UnderLyingType(Type type)
	    {
		    return type.IsValueType ? Nullable.GetUnderlyingType(type) : type;
	    }

	    private static IDataTable CreateDqDataTable(IList<string> columns, IEnumerable<Type> types)
        {
            var tbl = new ForwardOnlyDataTable(columns.Select(c => new DqDataColumn()), columns, types);
            return tbl;
        }

		private static object DefaultValue(Type type)
		{
			return type.IsValueType ? Activator.CreateInstance(type) : null;
		}
    }
}
